#include "segment.h"
#include "Precision.h"
#include <algorithm>

Segment::Segment()
{
}

Envelope Segment::GetEnvelope() const
{
    return Envelope(this->org().x(),this->dst().x(),this->org().y(),this->dst().y());
}

Line Segment::GetLine() const
{
    return Line(this->org(),this->dst());
}

Point::PointSiteEnum Segment::PointSite(const Point &p) const
{
    return Point::PointSite(p,this->org(),this->dst());
}

bool Segment::IsIntersect(const Segment &s1, const Segment &s2)
{
    if(!s1.GetEnvelope().IsIntersect(s2.GetEnvelope()))
        return false;

    Point::PointSiteEnum o,d;
    o = s1.PointSite(s2.org());
    d = s1.PointSite(s2.dst());
    if(o == d && o != Point::kPointOnLine)
        return false;

    o = s2.PointSite(s1.org());
    d = s2.PointSite(s1.dst());
    if(o == d && o != Point::kPointOnLine)
        return false;

    return true;
}


Segment::Intersection Segment::IntersectPoint(const Segment &other) const
{
    Segment::Intersection ret;
    if(!IsIntersect(*this,other))
    {
        ret.kind = kNull;
        return ret;
    }

    Line l1 = this->GetLine();
    Line l2 = other.GetLine();

    double x,y;
    if(!l1.Intersection(l2,x,y))
    {
        ret.kind = kSegment;
        Point ps[4] = {this->org(),this->dst(),other.org(),other.dst()};
        std::sort(ps,ps + 4);
        ret.result[0] = ps[1];
        ret.result[1] = ps[2];
        return ret;
    }
    else
    {
        ret.kind = kPoint;
        ret.result[0].set_x(x);
        ret.result[0].set_y(y);
    }

}
